var redisKey = require('../redisKey');
var utils = require('../utils');
var async = require('async');
var BaseService = require('./base-service').BaseService;

/**
 * 这个类主要用来操作与用户相关的数据
 * 
 * @class UserService
 */
class UserService extends BaseService {
    constructor(context) {
        super(context);
    }
    
    /**
     * 获取指定用户的计划信息
     * 
     * @param {String} userId - 指定的用户id
     * @param {Function} parentCallback - 完成调用后的毁掉函数
     */
    getPlanInfo(userId, parentCallback) {
        var me = this;
        this.acquireStorageClients({
            mysql: true,
            redis: true
        }, function(clients) {
            var mysql = clients.mysql;
            var redis = clients.redis;
            var userPlanKey = redisKey.user_plan(userId);
            var plan = {};
            async.waterfall([
                function(callback) {
                    redis.get(userPlanKey, (error, result) => {
                        if (error) {
                            me.reportError(utils.buildRedisError(error, {
                                user_id: userId,
                                stack: error.stack
                            }));
                        }
                        callback(null, result);
                    });
                },
                function(planStr, callback) {
                    if(planStr) {
                        me.releaseStorageClients(clients);
                        plan = JSON.parse(planStr);
                        parentCallback({
                            success: true,
                            data: plan
                        });
                    } else {
                        callback(null);
                    }
                },
                function(callback) {
                    me.getUserPlanData(mysql, userId, function(features) {
                        callback(null, features);
                    });
                }, function(features, callback) {
                    var planId = null;
                    var isActive = false;
                    var isTrial = false;
                    var startDate = null;
                    var endDate = null;
                    plan.features = {};
                    features.forEach(function(feature) {
                        planId = feature.plan_id;
                        isActive = Boolean(feature.is_active);
                        isTrial = Boolean(feature.is_trial);
                        startDate = new Date(feature.start_date).getTime();
                        endDate = new Date(feature.end_date).getTime();
                        var value = null;
                        switch(feature.value_type) {
                        case 'number':
                            value = Number(feature.value);
                            break;
                        case 'bool':
                            value = Boolean(feature.value);
                            break;
                        case 'constant':
                        default:
                            value = feature.value;
                            break;
                        }
                        plan.features[feature.identifier] = value;
                    });

                    plan.is_active = isActive;
                    plan.is_trial = isTrial;
                    plan.start_date = startDate;
                    plan.end_date = endDate;
                    plan.id = planId;

                    callback(null, planId);
                }, function(planId, callback) {
                    if(!planId) {
                        me.releaseStorageClients(clients);
                        parentCallback({
                            success: false,
                            error: 'No plan'
                        });
                    } else {
                        me.getPlanProductions(mysql, planId, function(productions) {
                            callback(null, productions);
                        });
                    }
                }, function(productions, callback) {
                    plan.productions = {};
                    productions.forEach(function(production) {
                        var handler = production.handler;
                        plan.productions[handler] = {
                            id: production.id,
                            name: production.name,
                            price: production.price,
                            price_type: production.price_type
                        };
                    });
                    redis.set(userPlanKey, JSON.stringify(plan), callback);
                }, function() {
                    me.releaseStorageClients(clients);
                    parentCallback({
                        success: true,
                        data: plan
                    })
                }
            ]);
        }, function(message) {
            parentCallback({
                success: false,
                error: message
            });
        });
    }
    /**
     * 从数据库中获取用户的计划数据
     * 
     * @param {Connection} mysql - MySQL Connection
     * @param {String} userId - 用户id
     * @param {Function} parentCallback - 数据返回的回调函数
     */
    getUserPlanData(mysql, userId, parentCallback) {
        var me = this;
        async.waterfall([
            function(callback) {
                mysql.query('CALL sp_wall_getUserPlanData(?)', [userId], (error, result) => {
                    if (error) {
                        me.reportError(utils.buildMySQLError(error, {
                            user_id: userId,
                            stack: error.stack
                        }));
                    }
                    callback(null, result);
                });
            }, function(result, callback) {
                if (!result) {
                    parentCallback([]);
                } else {
                    parentCallback(result[0]);
                }
            }
        ]);
    }

    /**
     * 获取与计划相关的货物
     * 
     * @param {Connection} mysql - MySQL Connection
     * @param {String} userId - 用户id
     * @param {Function} parentCallback - 数据返回的回调函数
     * 
     */
    getPlanProductions(mysql, planId, parentCallback) {
        var me = this;
        async.waterfall([
            function(callback) {
                mysql.query('CALL sp_wall_getPlanProductions(?)', [planId], (error, result) => {
                    if (error) {
                        me.reportError(utils.buildMySQLError(error, {
                            plan_id: planId,
                            stack: error.stack
                        }));
                    }
                    callback(null, result);
                });
            }, function(result, callback) {
                if (result) {
                    parentCallback(result[0]);
                } else {
                    parentCallback([]);
                }
            }
        ]);
    }
    /**
     * 为用户产生订阅计划
     * 
     * @name generateUserPlan
     * @param {Connection} mysql - MySQL Connection
     * @param {String} userId - 用户编号
     * @param {Number} planId - 计划编号
     * @param {Number} period - 时长
     * @param {String} periodType - 时长类别 daily|yearly
     * @param {Boolean} isTrial - 是否是试用
     * @param {Number} createdBy - 创建者
     * 
     * @returns {void}
     */
    generateUserPlan(orderId, userId, planId, period, periodType, isTrial, createdBy, parentCallback) {
        var me = this;
        var now = new Date();
        var endDate = new Date(now);

        switch(periodType) {
            case 'daily':
            var timestamp = endDate.getTime();
            endDate.setTime(timestamp + 86400 * period * 1000);
            break;
            case 'yearly':
            var year = endDate.getFullYear();
            endDate.setFullYear(year + period);
            break;
        }

        this.acquireStorageClients({
            mysql: true
        }, function(clients) {
            var mysql = clients.mysql;
            mysql.query('CALL sp_wall_generateUserPlan(?,?,?,?,?,?,?)', [orderId, planId, userId, me.formatDate(now), me.formatDate(endDate), isTrial, createdBy], function(error, result) {
                me.releaseStorageClients(clients);
                if(error) {
                    me.reportError(utils.buildMySQLError(error, {
                        order_id: orderId,
                        user_id: userId,
                        plan_id: planId,
                        period: period,
                        period_type: periodType,
                        is_trial: isTrial,
                        created_by: createdBy,
                        stack: error.stack
                    }));
                    parentCallback({
                        success: false,
                        error: "服务器暂时不可用，请稍后再试！"
                    });
                } else {
                    parentCallback({
                        success: true,
                        data: 'OK'
                    });
                }
            });
        }, function(message) {
            parentCallback({
                success: false,
                error: message
            });
        });
    }

    /**
     * Delete user plan
     * 
     * @name deleteUserPlan
     * @param {String} userId - The user id
     * @param {Function} parentCallback - The callback function
     * 
     * @returns {void}
     */
    deleteUserPlan(userId, parentCallback) {
        var me = this;
        this.acquireStorageClients({
            mysql: true
        }, (clients) => {
            var mysql = clients.mysql;
            mysql.query('CALL sp_wall_deleteUserPlan(?)', [userId], (error, result) => {
                if (error) {
                    return parentCallback({
                        success: false,
                        error: error.message
                    });
                }

                parentCallback({
                    success: true,
                    data: 'OK'
                });
            });
        }, (error) => {
            parentCallback({
                success: false,
                error: error.message
            })
        });
    }
}

exports.UserService = UserService;